using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Configuration
{
    /// <summary>
    /// 应用设置管理器实现
    /// 提供对 appsettings.json 配置文件的统一访问和管理功能
    /// </summary>
    public class AppSettingsManager : IAppSettingsManager
    {
        private readonly IConfiguration _configuration;
        private readonly ILogger<AppSettingsManager> _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="configuration">配置服务</param>
        /// <param name="logger">日志服务</param>
        public AppSettingsManager(IConfiguration configuration, ILogger<AppSettingsManager> logger)
        {
            _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        /// <summary>
        /// 获取指定键的配置值
        /// </summary>
        /// <typeparam name="T">返回值类型</typeparam>
        /// <param name="key">配置键，支持层级键（如："Database:ConnectionString"）</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>配置值</returns>
    public T GetValue<T>(string key, T defaultValue = default!)
        {
            try
            {
                var value = _configuration.GetValue(key, defaultValue);
                _logger.LogDebug("Configuration value retrieved: {Key} = {Value}", key, value);
                return value is null ? defaultValue! : value;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting configuration value for key: {Key}", key);
        return defaultValue!;
            }
        }

        /// <summary>
        /// 获取指定键的字符串配置值
        /// </summary>
        /// <param name="key">配置键</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>配置值</returns>
        public string GetStringValue(string key, string? defaultValue = null)
        {
            return GetValue(key, defaultValue) ?? string.Empty;
        }

        /// <summary>
        /// 获取指定键的整数配置值
        /// </summary>
        /// <param name="key">配置键</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>配置值</returns>
        public int GetIntValue(string key, int defaultValue = 0)
        {
            return GetValue(key, defaultValue);
        }

        /// <summary>
        /// 获取指定键的布尔配置值
        /// </summary>
        /// <param name="key">配置键</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>配置值</returns>
        public bool GetBoolValue(string key, bool defaultValue = false)
        {
            return GetValue(key, defaultValue);
        }

        /// <summary>
        /// 获取指定配置节的所有子配置
        /// </summary>
        /// <param name="sectionKey">配置节键</param>
        /// <returns>配置字典</returns>
        public IDictionary<string, string> GetSection(string sectionKey)
        {
            try
            {
                var section = _configuration.GetSection(sectionKey);
                var result = new Dictionary<string, string>();

                if (section.Exists())
                {
                    foreach (var child in section.GetChildren())
                    {
                        GetFlattenedValues(child, child.Key, result);
                    }
                }

                _logger.LogDebug("Configuration section retrieved: {SectionKey} with {Count} items", sectionKey, result.Count);
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting configuration section: {SectionKey}", sectionKey);
                return new Dictionary<string, string>();
            }
        }

        /// <summary>
        /// 绑定配置节到指定的对象类型
        /// </summary>
        /// <typeparam name="T">目标对象类型</typeparam>
        /// <param name="sectionKey">配置节键</param>
        /// <returns>绑定后的对象实例</returns>
        public T GetSection<T>(string sectionKey) where T : class, new()
        {
            try
            {
                var instance = new T();
                _configuration.GetSection(sectionKey).Bind(instance);
                _logger.LogDebug("Configuration section bound to type {Type}: {SectionKey}", typeof(T).Name, sectionKey);
                return instance;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error binding configuration section {SectionKey} to type {Type}", sectionKey, typeof(T).Name);
                return new T();
            }
        }

        /// <summary>
        /// 获取数据库连接字符串
        /// </summary>
        /// <param name="name">连接字符串名称</param>
        /// <returns>连接字符串</returns>
        public string GetConnectionString(string name)
        {
            try
            {
                var connectionString = _configuration.GetConnectionString(name);
                _logger.LogDebug("Connection string retrieved: {Name}", name);
                return connectionString ?? string.Empty;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting connection string: {Name}", name);
                return string.Empty;
            }
        }

        /// <summary>
        /// 检查指定配置键是否存在
        /// </summary>
        /// <param name="key">配置键</param>
        /// <returns>是否存在</returns>
        public bool HasKey(string key)
        {
            try
            {
                return _configuration.GetSection(key).Exists();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error checking if key exists: {Key}", key);
                return false;
            }
        }

        /// <summary>
        /// 获取所有配置键值对
        /// </summary>
        /// <returns>配置键值对字典</returns>
    public IDictionary<string, string> GetAllSettings()
        {
            try
            {
                var result = new Dictionary<string, string>();
        GetFlattenedValues(_configuration.AsEnumerable(), result);
                _logger.LogDebug("All configuration settings retrieved: {Count} items", result.Count);
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting all configuration settings");
                return new Dictionary<string, string>();
            }
        }

        /// <summary>
        /// 重新加载配置
        /// </summary>
        public void Reload()
        {
            try
            {
                if (_configuration is IConfigurationRoot root)
                {
                    root.Reload();
                    _logger.LogInformation("Configuration reloaded successfully");
                }
                else
                {
                    _logger.LogWarning("Configuration reload not supported for this configuration type");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error reloading configuration");
            }
        }

        /// <summary>
        /// 获取配置变更通知
        /// </summary>
        /// <param name="callback">配置变更回调</param>
        /// <returns>变更令牌</returns>
    public IDisposable? OnChange(Action callback)
        {
            try
            {
                return _configuration.GetReloadToken().RegisterChangeCallback(_ => callback?.Invoke(), null);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error setting up configuration change callback");
        return null;
            }
        }

        /// <summary>
        /// 递归获取扁平化的配置值
        /// </summary>
        /// <param name="section">配置节</param>
        /// <param name="prefix">前缀</param>
        /// <param name="result">结果字典</param>
        private void GetFlattenedValues(IConfigurationSection section, string prefix, IDictionary<string, string> result)
        {
            if (section.Value != null)
            {
                result[prefix] = section.Value;
            }
            else
            {
                foreach (var child in section.GetChildren())
                {
                    GetFlattenedValues(child, $"{prefix}:{child.Key}", result);
                }
            }
        }

        /// <summary>
        /// 从键值对枚举中获取扁平化的配置值
        /// </summary>
        /// <param name="source">键值对枚举</param>
        /// <param name="result">结果字典</param>
        private void GetFlattenedValues(IEnumerable<KeyValuePair<string, string?>> source, IDictionary<string, string> result)
        {
            foreach (var kvp in source.Where(x => x.Value != null))
            {
                result[kvp.Key] = kvp.Value!;
            }
        }
    }
}
